using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Main : MonoBehaviour
{

    public Sprite[] SpriteElements;
    public RectTransform TileUnit;

    Dictionary<Vector2Int, RectTransform> PresentTiles = new Dictionary<Vector2Int, RectTransform>();
    const int ElementSize = 20;
    int TileSize {
        get { return ElementSize * 2; }
    }

    enum TilePart { 
        LU,
        RU,
        LD,
        RD,
        count
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0)) {
            
            Vector2Int TileIndex = new Vector2Int();
            TileIndex.x = Mathf.FloorToInt(Input.mousePosition.x / TileSize);
            TileIndex.y = Mathf.FloorToInt(Input.mousePosition.y / TileSize);
           
            if (!PresentTiles.ContainsKey(TileIndex))
            {
                // add 
                var NewTile = Instantiate(TileUnit.gameObject).GetComponent<RectTransform>();
                NewTile.SetParent(TileUnit.parent);
                NewTile.anchoredPosition = new Vector2(TileIndex.x * TileSize, TileIndex.y * TileSize);
                PresentTiles.Add(TileIndex, NewTile);
            }
            else {
                // delete 
                Destroy(PresentTiles[TileIndex].gameObject);
                PresentTiles.Remove(TileIndex);
            }
            RefreshPresentTiles();

        }
    }

    void RefreshPresentTiles() {
        foreach (var Tile in PresentTiles)
        {
            for (int i = 0; i < (int)TilePart.count; i++)
            {
                TilePart part = (TilePart)i;
                Tile.Value.Find(part.ToString())
                    .GetComponent<UnityEngine.SpriteRenderer>().sprite
                    = SpriteElements[GetExpectElementIndex(Tile.Key, part)];
                print(part.ToString()+":"+GetExpectElementIndex(Tile.Key, part));
            }
        }
    }

    int GetExpectElementIndex(Vector2Int TileIndex, TilePart Part) {

        var NeighbourFilled = new System.Func<Vector2Int, bool>((NeighbourOffset) =>
        {
            return PresentTiles.ContainsKey(TileIndex + NeighbourOffset);
        });

        bool Up = NeighbourFilled(new Vector2Int(0, 1));
        bool Down = NeighbourFilled(new Vector2Int(0, -1));
        bool Left = NeighbourFilled(new Vector2Int(-1, 0));
        bool Right = NeighbourFilled(new Vector2Int(1, 0));
        bool LeftUp = NeighbourFilled(new Vector2Int(-1, 1));
        bool RightUp = NeighbourFilled(new Vector2Int(1, 1));
        bool LeftDown = NeighbourFilled(new Vector2Int(-1, -1));
        bool RightDown = NeighbourFilled(new Vector2Int(1, -1));

        switch (Part) {
            case TilePart.LU:
                if (Up && Left)
                {
                    if (LeftUp) return 11;
                    else return 17;
                }
                else if (!(Up || Left))
                {
                    return 1;
                }
                else
                {
                    if (Up) return 9;
                    else return 3;
                }
            case TilePart.RU:
                if (Up && Right)
                {
                    if (RightUp) return 10;
                    else return 18;
                }
                else if (!(Up || Right))
                {
                    return 4;
                }
                else
                {
                    if (Up) return 12;
                    else return 2;
                }
            case TilePart.LD:
                if (Down && Left)
                {
                    if (LeftDown) return 7;
                    else return 19;
                }
                else if (!(Down || Left))
                {
                    return 13;
                }
                else {
                    if (Down) return 5;
                    else return 15;
                }
            case TilePart.RD:
                if (Down && Right)
                {
                    if (RightDown) return 6;
                    else return 20;
                }
                else if (!(Down || Right))
                {
                    return 16;
                }
                else {
                    if (Down) return 8;
                    else return 14;
                }
        }
        return 0;
    }
}
